/*
 * Wazuh Vulnerability Scanner - Unit Tests
 * Copyright (C) 2015, Wazuh Inc.
 * September 21, 2023.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#include "storeModel_test.hpp"
#include "cve5_schema.h"
#include "databaseFeedManager/eventContext.hpp"
#include "databaseFeedManager/storeModel.hpp"
#include "flatbuffers/idl.h"
#include <memory>
#include <string>
#include <vector>

const std::string CVE_UPDATE_EXAMPLE_SUCCESS {"CVE-2022-0605"};

const std::string CVE5_ENTRY_PUBLISHED = R"(
            {
                "containers": {
                    "cna": {
                        "affected": [
                            {
                            "cpes": [
                                "cpe:2.3:a:google:chrome:*:*:*:*:*:*:*:*"
                            ],
                            "defaultStatus": "unaffected",
                            "product": "chrome",
                            "vendor": "google",
                            "versions": [
                                {
                                "lessThan": "98.0.4758.102",
                                "status": "affected",
                                "version": "0",
                                "versionType": "custom"
                                }
                            ]
                            }
                        ],
                        "descriptions": [
                            {
                            "lang": "en",
                            "value": "Use after free in Webstore API in Google Chrome prior to 98.0.4758.102 allowed an attacker who convinced a user to install a malicious extension and convinced a user to enage in specific user interaction to potentially exploit heap corruption via a crafted HTML page."
                            }
                        ],
                        "metrics": [
                            {
                            "cvssV3_1": {
                                "attackComplexity": "LOW",
                                "attackVector": "NETWORK",
                                "availabilityImpact": "HIGH",
                                "baseScore": 8.8,
                                "baseSeverity": "HIGH",
                                "confidentialityImpact": "HIGH",
                                "integrityImpact": "HIGH",
                                "privilegesRequired": "NONE",
                                "scope": "UNCHANGED",
                                "userInteraction": "REQUIRED",
                                "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
                                "version": "3.1"
                            },
                            "format": "CVSS"
                            }
                        ],
                        "problemTypes": [
                            {
                            "descriptions": [
                                {
                                "description": "CWE-416",
                                "lang": "en"
                                }
                            ]
                            }
                        ],
                        "providerMetadata": {
                            "orgId": "00000000-0000-4000-A000-000000000003",
                            "shortName": "nvd",
                            "dateUpdated": "2022-04-11T09:33:00Z"
                        },
                        "references": [
                            {
                            "name": "https://crbug.com/1286940",
                            "tags": [
                                "issue-tracking",
                                "permissions-required",
                                "vendor-advisory"
                            ],
                            "url": "https://crbug.com/1286940"
                            }
                        ]
                    }
                },
                "cveMetadata": {
                    "assignerOrgId": "00000000-0000-4000-A000-000000000003",
                    "assignerShortName": "nvd",
                    "cveId": "CVE-2022-0605",
                    "datePublished": "2022-04-05T00:15:00Z",
                    "dateUpdated": "2022-04-11T09:33:00Z",
                    "state": "PUBLISHED"
                },
                "dataType": "CVE_RECORD",
                "dataVersion": "5.0"
            }
        )";

const std::string CVE5_ENTRY_REJECTED = R"(
        {
            "containers": {
                "cna": {
                    "providerMetadata": {
                        "dateUpdated": "2023-03-09T14:02:53Z",
                        "orgId": "00000000-0000-4000-A000-000000000003",
                        "shortName": "nvd"
                    },
                    "rejectedReasons": [
                        {
                            "lang": "en",
                            "value": "This candidate was in a CNA pool that was not assigned to any issues during 2022."
                        }
                    ]
                }
            },
            "cveMetadata": {
                "assignerOrgId": "00000000-0000-4000-A000-000000000003",
                "assignerShortName": "nvd",
                "cveId": "CVE-2022-26053",
                "datePublished": "2023-03-07T23:15:10Z",
                "dateUpdated": "2023-03-09T14:02:53Z",
                "state": "REJECTED"
            },
            "dataType": "CVE_RECORD",
            "dataVersion": "5.0"
        }
    )";

const std::string CVE5_ENTRY_INVALID_STATE = R"(
        {
            "containers": {
                "cna": {
                    "providerMetadata": {
                        "dateUpdated": "2023-03-09T14:02:53Z",
                        "orgId": "00000000-0000-4000-A000-000000000003",
                        "shortName": "nvd"
                    },
                    "rejectedReasons": [
                        {
                            "lang": "en",
                            "value": "This candidate was in a CNA pool that was not assigned to any issues during 2022."
                        }
                    ]
                }
            },
            "cveMetadata": {
                "assignerOrgId": "00000000-0000-4000-A000-000000000003",
                "assignerShortName": "nvd",
                "cveId": "CVE-2022-26053",
                "datePublished": "2023-03-07T23:15:10Z",
                "dateUpdated": "2023-03-09T14:02:53Z",
                "state": "INVALID"
            },
            "dataType": "CVE_RECORD",
            "dataVersion": "5.0"
        }
    )";

/*
 * @brief Test handleRequest of the StoreModel class.
 */
TEST_F(StoreModelTest, TestHandleRequestCreate)
{
    std::string message;
    nlohmann::json resource;
    resource["type"] = "create";

    flatbuffers::Parser parser;
    ASSERT_TRUE(parser.Parse(cve5_SCHEMA) && parser.Parse(CVE5_ENTRY_PUBLISHED.c_str()));

    flatbuffers::FlatBufferBuilder& builder = parser.builder_;

    auto feedDatabase = std::make_shared<Utils::RocksDBWrapper>("temp");
    auto eventContext = std::make_shared<EventContext>(EventContext {
        .message = message, .resource = resource, .feedDatabase = feedDatabase, .resourceType = ResourceType::CVE});

    eventContext->cve5Buffer = builder.Release();

    std::shared_ptr<StoreModel> storeModel;

    // Instantiation of the StoreModel class.
    EXPECT_NO_THROW(storeModel = std::make_shared<StoreModel>());

    // HandleRequest
    EXPECT_NO_THROW(storeModel->handleRequest(eventContext));
}

TEST_F(StoreModelTest, TestHandleRequestUpdate)
{
    std::string message;
    nlohmann::json resource;
    resource["type"] = "update";

    flatbuffers::Parser parser;
    ASSERT_TRUE(parser.Parse(cve5_SCHEMA) && parser.Parse(CVE5_ENTRY_PUBLISHED.c_str()));

    flatbuffers::FlatBufferBuilder& builder = parser.builder_;

    auto feedDatabase = std::make_shared<Utils::RocksDBWrapper>("temp");
    auto eventContext = std::make_shared<EventContext>(EventContext {
        .message = message, .resource = resource, .feedDatabase = feedDatabase, .resourceType = ResourceType::CVE});

    eventContext->cve5Buffer = builder.Release();

    std::shared_ptr<StoreModel> storeModel;

    // Instantiation of the StoreModel class.
    EXPECT_NO_THROW(storeModel = std::make_shared<StoreModel>());

    // HandleRequest
    EXPECT_NO_THROW(storeModel->handleRequest(eventContext));
}

TEST_F(StoreModelTest, TestInvalidEventType)
{
    std::string message;
    nlohmann::json resource;

    flatbuffers::Parser parser;
    ASSERT_TRUE(parser.Parse(cve5_SCHEMA) && parser.Parse(CVE5_ENTRY_PUBLISHED.c_str()));

    flatbuffers::FlatBufferBuilder& builder = parser.builder_;

    auto feedDatabase = std::make_shared<Utils::RocksDBWrapper>("temp");
    auto eventContext = std::make_shared<EventContext>(EventContext {
        .message = message, .resource = resource, .feedDatabase = feedDatabase, .resourceType = ResourceType::CVE});

    eventContext->cve5Buffer = builder.Release();

    std::shared_ptr<StoreModel> storeModel;

    // Instantiation of the StoreModel class.
    EXPECT_NO_THROW(storeModel = std::make_shared<StoreModel>());

    // HandleRequest
    EXPECT_THROW(storeModel->handleRequest(eventContext), std::runtime_error);
}

TEST_F(StoreModelTest, TestInvalidEntryState)
{
    std::string message;
    nlohmann::json resource;
    resource["type"] = "update";

    flatbuffers::Parser parser;
    ASSERT_TRUE(parser.Parse(cve5_SCHEMA) && parser.Parse(CVE5_ENTRY_INVALID_STATE.c_str()));

    flatbuffers::FlatBufferBuilder& builder = parser.builder_;

    auto feedDatabase = std::make_shared<Utils::RocksDBWrapper>("temp");
    auto eventContext = std::make_shared<EventContext>(EventContext {
        .message = message, .resource = resource, .feedDatabase = feedDatabase, .resourceType = ResourceType::CVE});

    eventContext->cve5Buffer = builder.Release();

    std::shared_ptr<StoreModel> storeModel;

    // Instantiation of the StoreModel class.
    EXPECT_NO_THROW(storeModel = std::make_shared<StoreModel>());

    // HandleRequest
    EXPECT_THROW(storeModel->handleRequest(eventContext), std::runtime_error);
}

TEST_F(StoreModelTest, TestEmptyBuffer)
{
    std::string message;
    nlohmann::json resource;
    resource["type"] = "update";

    auto feedDatabase = std::make_shared<Utils::RocksDBWrapper>("temp");
    auto eventContext = std::make_shared<EventContext>(EventContext {
        .message = message, .resource = resource, .feedDatabase = feedDatabase, .resourceType = ResourceType::CVE});

    std::shared_ptr<StoreModel> storeModel;

    // Instantiation of the StoreModel class.
    EXPECT_NO_THROW(storeModel = std::make_shared<StoreModel>());

    // HandleRequest
    EXPECT_THROW(storeModel->handleRequest(eventContext), std::runtime_error);
}
